package com.study.tomcat.v3;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.Principal;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author: chenhs
 * @date: Created in 15:16 2019/12/21
 **/
public class TomcatServerV3 {

    private static ThreadFactory nameThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();

    private static ExecutorService threadPool = new ThreadPoolExecutor(5, 200
            , 0L, TimeUnit.MILLISECONDS
            , new LinkedBlockingQueue<>(1024), nameThreadFactory, new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) throws Exception {
        //todo 具体执行之前，肯定会有加载项目信息【类加载 配置文件】
        Map<String, ProjectUtil.WebXml> projectInfo = ProjectUtil.load();

        ServerSocket serverSocket = new ServerSocket(8080);

        System.out.println("tomcat 服务器启动成功！");
        while (!serverSocket.isClosed()) {
            //获取新链接 （请求、响应）（浏览器/httpClient发起的请求）
            //阻塞
            Socket socket = serverSocket.accept();
            threadPool.submit(()->{
                try {
                    //接收数据，打印
                    InputStream inputStream = socket.getInputStream();
                    // System.out.println("收到请求：");
                    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
                    String msg;
                    StringBuilder requestInfo = new StringBuilder();
                    while ((msg= reader.readLine()) != null) {
                        if (msg.length() == 0) {
                            break;
                        }
                        requestInfo.append(msg).append("\r\n");
                    }

                    System.out.println("-------------------------------收到请求："+ requestInfo);
                    // todo 调用项目业务代码 GET /servlet-demo-1.0.0/index HTTP/1.1
                    // 1、对应的项目名：/servlet-demo-1.0.0
                    String firstLine = requestInfo.toString().split("\r\n")[0];
                    String projectName = firstLine.split(" ")[1].split("/")[1];

                    // 2、对应的servlet名称：/index
                    String servletPath = firstLine.split(" ")[1].replace("/"+ projectName, "");

                    // 3、执行servlet【难点：一个运行中的jvm，去执行某一个class里面的业务代码】
                    String servletName = projectInfo.get(projectName).servletMapping.get(servletPath);
                    Servlet servlet = projectInfo.get(projectName).servletInstances.get(servletName);

                    HttpServletRequest servletRequest = createRequest(requestInfo.toString());
                    HttpServletResponse servletResponse = createResponse();

                    servlet.service(servletRequest, servletResponse);

                    OutputStream outputStream = socket.getOutputStream();
                    outputStream.write("HTTP/1.1 200 OK\r\n".getBytes());
                    outputStream.write("Content-Length: 11\r\n\r\n".getBytes());
                    outputStream.write("Hello World\r\n".getBytes());
                    outputStream.flush();

                    socket.close();
                } catch (IOException | ServletException e) {
                    e.printStackTrace();
                }

            });
        }
        serverSocket.close();
    }


    private static HttpServletResponse createResponse() {
        return new HttpServletResponse() {
            @Override
            public String getCharacterEncoding() {
                return null;
            }

            @Override
            public String getContentType() {
                return null;
            }

            @Override
            public ServletOutputStream getOutputStream() throws IOException {
                return null;
            }

            @Override
            public PrintWriter getWriter() throws IOException {
                return null;
            }

            @Override
            public void setCharacterEncoding(String charset) {

            }

            @Override
            public void setContentLength(int len) {

            }

            @Override
            public void setContentType(String type) {

            }

            @Override
            public void setBufferSize(int size) {

            }

            @Override
            public int getBufferSize() {
                return 0;
            }

            @Override
            public void flushBuffer() throws IOException {

            }

            @Override
            public void resetBuffer() {

            }

            @Override
            public boolean isCommitted() {
                return false;
            }

            @Override
            public void reset() {

            }

            @Override
            public void setLocale(Locale loc) {

            }

            @Override
            public Locale getLocale() {
                return null;
            }

            @Override
            public void addCookie(Cookie cookie) {

            }

            @Override
            public boolean containsHeader(String name) {
                return false;
            }

            @Override
            public String encodeURL(String url) {
                return null;
            }

            @Override
            public String encodeRedirectURL(String url) {
                return null;
            }

            @Override
            public String encodeUrl(String url) {
                return null;
            }

            @Override
            public String encodeRedirectUrl(String url) {
                return null;
            }

            @Override
            public void sendError(int sc, String msg) throws IOException {

            }

            @Override
            public void sendError(int sc) throws IOException {

            }

            @Override
            public void sendRedirect(String location) throws IOException {

            }

            @Override
            public void setDateHeader(String name, long date) {

            }

            @Override
            public void addDateHeader(String name, long date) {

            }

            @Override
            public void setHeader(String name, String value) {

            }

            @Override
            public void addHeader(String name, String value) {

            }

            @Override
            public void setIntHeader(String name, int value) {

            }

            @Override
            public void addIntHeader(String name, int value) {

            }

            @Override
            public void setStatus(int sc) {

            }

            @Override
            public void setStatus(int sc, String sm) {

            }
        };
    }

    private static HttpServletRequest createRequest(String requestContent) {
        return new HttpServletRequest() {
            @Override
            public String getMethod() {
                // GET /servlet-demo-1.0.0/index HTTP/1.1
                 String firstLine = requestContent.split("\r\n")[0];

                return "GET";
            }

            @Override
            public String getAuthType() {
                return null;
            }

            @Override
            public Cookie[] getCookies() {
                return new Cookie[0];
            }

            @Override
            public long getDateHeader(String name) {
                return 0;
            }

            @Override
            public String getHeader(String name) {
                return null;
            }

            @Override
            public Enumeration getHeaders(String name) {
                return null;
            }

            @Override
            public Enumeration getHeaderNames() {
                return null;
            }

            @Override
            public int getIntHeader(String name) {
                return 0;
            }

            @Override
            public String getPathInfo() {
                return null;
            }

            @Override
            public String getPathTranslated() {
                return null;
            }

            @Override
            public String getContextPath() {
                return null;
            }

            @Override
            public String getQueryString() {
                return null;
            }

            @Override
            public String getRemoteUser() {
                return null;
            }

            @Override
            public boolean isUserInRole(String role) {
                return false;
            }

            @Override
            public Principal getUserPrincipal() {
                return null;
            }

            @Override
            public String getRequestedSessionId() {
                return null;
            }

            @Override
            public String getRequestURI() {
                return null;
            }

            @Override
            public StringBuffer getRequestURL() {
                return null;
            }

            @Override
            public String getServletPath() {
                return null;
            }

            @Override
            public HttpSession getSession(boolean create) {
                return null;
            }

            @Override
            public HttpSession getSession() {
                return null;
            }

            @Override
            public boolean isRequestedSessionIdValid() {
                return false;
            }

            @Override
            public boolean isRequestedSessionIdFromCookie() {
                return false;
            }

            @Override
            public boolean isRequestedSessionIdFromURL() {
                return false;
            }

            @Override
            public boolean isRequestedSessionIdFromUrl() {
                return false;
            }

            @Override
            public Object getAttribute(String name) {
                return null;
            }

            @Override
            public Enumeration getAttributeNames() {
                return null;
            }

            @Override
            public String getCharacterEncoding() {
                return null;
            }

            @Override
            public void setCharacterEncoding(String env) throws UnsupportedEncodingException {

            }

            @Override
            public int getContentLength() {
                return 0;
            }

            @Override
            public String getContentType() {
                return null;
            }

            @Override
            public ServletInputStream getInputStream() throws IOException {
                return null;
            }

            @Override
            public String getParameter(String name) {
                return null;
            }

            @Override
            public Enumeration getParameterNames() {
                return null;
            }

            @Override
            public String[] getParameterValues(String name) {
                return new String[0];
            }

            @Override
            public Map getParameterMap() {
                return null;
            }

            @Override
            public String getProtocol() {
                return null;
            }

            @Override
            public String getScheme() {
                return null;
            }

            @Override
            public String getServerName() {
                return null;
            }

            @Override
            public int getServerPort() {
                return 0;
            }

            @Override
            public BufferedReader getReader() throws IOException {
                return null;
            }

            @Override
            public String getRemoteAddr() {
                return null;
            }

            @Override
            public String getRemoteHost() {
                return null;
            }

            @Override
            public void setAttribute(String name, Object o) {

            }

            @Override
            public void removeAttribute(String name) {

            }

            @Override
            public Locale getLocale() {
                return null;
            }

            @Override
            public Enumeration getLocales() {
                return null;
            }

            @Override
            public boolean isSecure() {
                return false;
            }

            @Override
            public RequestDispatcher getRequestDispatcher(String path) {
                return null;
            }

            @Override
            public String getRealPath(String path) {
                return null;
            }

            @Override
            public int getRemotePort() {
                return 0;
            }

            @Override
            public String getLocalName() {
                return null;
            }

            @Override
            public String getLocalAddr() {
                return null;
            }

            @Override
            public int getLocalPort() {
                return 0;
            }
        };
    }


}
